﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Natural.Model;
using Natural.Helpers;
using Natural.Managers;

namespace Natural.Providers
{
    public sealed class Executor
    {
        #region Execute
        public static object Execute<T>(InvokeContext context, string action, params object[] parameters)
        {
            return Execute(context, typeof(T).Name, action, parameters);
        }
        public static object Execute(InvokeContext context, string action, params object[] parameters)
        {
            return Execute(context, null, action, parameters);
        }
        public static object Execute<T>(ActionContext context, string action, params object[] parameters)
        {
            return Execute(context, typeof(T).Name, action, parameters);
        }
        public static object Execute(ActionContext context, string action, params object[] parameters)
        {
            return Execute(context, null, action, parameters);
        }
        public static object Execute(InvokeContext context, string entity, string action, params object[] parameters)
        {
            ActionInfo actionInfo = Solver.ActionInfo(entity, action);
            return Execute(context, actionInfo, parameters);
        }
        public static object Execute(ActionContext context, string entity, string action, params object[] parameters)
        {
            ActionInfo actionInfo = Solver.ActionInfo(entity, action);
            return Execute(context, actionInfo, parameters);
        }
        public static object Execute(InvokeContext context, ActionInfo actionInfo, params object[] parameters)
        {
            return Execute(context, new ActionRequest() { ActionInfo = actionInfo, Parameters = parameters }).Result;
        }
        public static object Execute(ActionContext context, ActionInfo actionInfo, params object[] parameters)
        {
            return Execute(context, new ActionRequest() { ActionInfo = actionInfo, Parameters = parameters }).Result;
        }
        public static ActionResponse Execute(ActionContext context, ActionRequest request)
        {
            ActionContext actionContext = new ActionContext(context) { Request = request, Response = new ActionResponse() };
            Manager.Execute(actionContext);
            return actionContext.Response;
        }
        public static ActionResponse Execute(InvokeContext context, ActionRequest request)
        {
            ActionContext actionContext = new ActionContext(context) { Request = request, Response = new ActionResponse() };
            Manager.Execute(actionContext);
            return actionContext.Response;
        }
        #endregion

        #region QuickActions
        public static List<object[]> Query(InvokeContext context, Expression expression)
        {
            return Execute(context, "Query", expression) as List<object[]>;
        }
        public static List<object[]> Query(ActionContext context, Expression expression)
        {
            return Execute(context, "Query", expression) as List<object[]>;
        }
        public static T[] Get<T>(InvokeContext context, Expression expression) where T : class
        {
            return Execute(context, typeof(T).Name, "Get", expression) as T[];
        }
        public static T[] Get<T>(ActionContext context, Expression expression) where T : class
        {
            return Execute(context, typeof(T).Name, "Get", expression) as T[];
        }
        public static T First<T>(InvokeContext context, Expression expression) where T : class
        {
            if (expression.Page == null) expression.Page = new Page() { Number = 1, Size = 1 };
            return (Execute(context, typeof(T).Name, "Get", expression) as T[]).FirstOrDefault();
        }
        public static T First<T>(ActionContext context, Expression expression) where T : class
        {
            if (expression.Page == null) expression.Page = new Page() { Number = 1, Size = 1 };
            return (Execute(context, typeof(T).Name, "Get", expression) as T[]).FirstOrDefault();
        }
        public static void Update<T>(InvokeContext context, T entity) where T : class
        {
            Execute(context, typeof(T).Name, "Update", entity);
        }
        public static void Update<T>(ActionContext context, T entity) where T : class
        {
            Execute(context, typeof(T).Name, "Update", entity);
        }
        public static void Delete<T>(InvokeContext context, T entity) where T : class
        {
            Execute(context, typeof(T).Name, "Delete", entity);
        }
        public static void Delete<T>(ActionContext context, T entity) where T : class
        {
            Execute(context, typeof(T).Name, "Delete", entity);
        }
        #endregion

        private static IExecutor Manager
        {
            get { return Solver.Solve("Executor") as IExecutor; }
        }
    }

}
